package
{
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.events.MouseEvent;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	
	public class MatchThree extends MovieClip
	{
		private static const SPACING:uint=45;
		private static const NUM_PIECE:uint=7;
		private static const OFFSET_X:uint=100;
		private static const OFFSET_Y:uint=50;
		
		private var grid:Array;
		private var gameSprite:Sprite;
		private var firstPiece:Piece;
		private var isDropping:Boolean;
		private var isSwapping:Boolean;
		public var gameScore:int;
		private var score:MovieClip=new MovieClip();
		private var gameTime:int=30;
		private var time:Timer;
		private var tsNum:int=3;
		private var clNum:int=3;
		private var isTs:Boolean=false;
		private var sisuo:TextField=new TextField();
		public function startMatchThree()
		{
			grid=new Array();
			displayTime.text="30";
			dispTs.text=tsNum.toString();
			dispCl.text=clNum.toString();
			scoreDisplay.text='0';
			dispTs.selectable=false;
			dispCl.selectable=false;
			updateTime();
			for(var i:uint=0;i<8;i++)
			{
				grid.push(new Array());
			}
			setUpGrid();
			isDropping=false;
			isSwapping=false;
			gameScore=0;
			findAndRemoveMatches();
			addEventListener(Event.ENTER_FRAME,movePieces);
			tsButton.addEventListener(MouseEvent.CLICK,Ts);
			clButton.addEventListener(MouseEvent.CLICK,Cl);
		}
		private function Ts(evt:MouseEvent)
		{
			isTs=true;
			lookForPossibles();
			tsNum--;
			dispTs.text=tsNum.toString();
			if(tsNum==0)
				tsButton.removeEventListener(MouseEvent.CLICK,Ts);
		}
		private function Cl(evt:MouseEvent)
		{
			for(var i:int=0;i<8;i++)
			{
				for(var j:int=0;j<8;j++)
				{
					gameSprite.removeChild(grid[i][j]);
					grid[i][j]=null;
				}
			}
			if(gameSprite.contains(sisuo))
				gameSprite.removeChild(sisuo);
			clNum--;
			dispCl.text=clNum.toString();
			if(clNum==0)
				clButton.removeEventListener(MouseEvent.CLICK,Cl);
			addNewPieces();
			time.start();
		}
		private function updateTime()
		{
			time=new Timer(1000);
			time.start(); 
			time.addEventListener(TimerEvent.TIMER,onCom);
		}
		private function onCom(evt:TimerEvent)
		{		
			if(gameTime==1)
			{
				gameTime=0;
				displayTime.text='0';
				removeEventListener(Event.ENTER_FRAME,movePieces);
				time.removeEventListener(TimerEvent.TIMER,onCom);
				time=null;
					
				grid=null;
				removeChild(gameSprite);
				gameSprite=null;
				gotoAndStop('gameover');			
			}
			else
			{
				gameTime-=1;
				displayTime.text=gameTime.toString();
			}
		}
		private function movePieces(evt:Event)
		{
			var madeMove:Boolean=false;
			for(var row:uint=0;row<8;row++)
			{
				for(var col:uint=0;col<8;col++)
				{
					if(grid[row][col]!=null)
					{
						//up
						if(grid[row][col].y>grid[row][col].row*SPACING+OFFSET_Y)
						{
							grid[row][col].y-=5;
							madeMove=true;
						}						
						//down
						if(grid[row][col].y<grid[row][col].row*SPACING+OFFSET_Y)
						{	
							grid[row][col].y+=5;
							madeMove=true;
						}
						//left
						if(grid[row][col].x>grid[row][col].col*SPACING+OFFSET_X)
						{	
							grid[row][col].x-=5;
							madeMove=true;
						}
						//right
						if(grid[row][col].x<grid[row][col].col*SPACING+OFFSET_X)
						{	
							grid[row][col].x+=5;
							madeMove=true;
						}
					}
				}
			}
			if(isSwapping && !madeMove)
			{
				isSwapping=false;
				findAndRemoveMatches();
			}
			else if(isDropping && !madeMove)
			{
				isDropping=false;
				findAndRemoveMatches();
			}
		}
		private function setUpGrid()
		{
			gameSprite=new Sprite();
			for(var row:uint=0;row<8;row++)
			{
				for(var col:uint=0;col<8;col++)
				{
					addPiece(row,col);
				}
			}
			addChild(gameSprite);
		}
		private function addPiece(row:uint,col:uint):Piece
		{
			var newPiece:Piece=new Piece();
			newPiece.x=col*SPACING+OFFSET_X;
			newPiece.y=row*SPACING+OFFSET_Y;
			newPiece.row=row;
			newPiece.col=col;
			newPiece.type=Math.ceil(Math.random()*7);
			newPiece.gotoAndStop(newPiece.type);
			newPiece.select.visible=false;
			grid[row][col]=newPiece;
			newPiece.addEventListener(MouseEvent.CLICK,onMouseClick);
			gameSprite.addChild(newPiece);
			return newPiece;
		}
		private function onMouseClick(evt:MouseEvent)
		{
			var curPiece:Piece=evt.currentTarget as Piece;
			if(firstPiece==null)
			{
				firstPiece=curPiece;
				firstPiece.select.visible=true;
			}
			else if(firstPiece==curPiece)
			{
				firstPiece.select.visible=false;
				firstPiece=null;
			}
			else
			{
				firstPiece.select.visible=false;
				if(firstPiece.row==curPiece.row&&Math.abs(firstPiece.col-curPiece.col)==1)
				{
					makeSwap(firstPiece,curPiece);
					firstPiece=null;
				}
				else if(firstPiece.col==curPiece.col&&Math.abs(firstPiece.row-curPiece.row)==1)
				{
					makeSwap(firstPiece,curPiece);
					firstPiece=null;
				}
				else
				{
				//	firstPiece.select.visible=false;
					firstPiece=curPiece;
					firstPiece.select.visible=true;
				}
			}
		}
		private function makeSwap(piece1:Piece,piece2:Piece)
		{
			swapPiece(piece1,piece2);
			if(lookForMatches().length==0)
				swapPiece(piece1,piece2);
			else
				isSwapping=true;
		}
		private function swapPiece(piece1:Piece,piece2:Piece)
		{
			var tempRow:uint;
			var tempCol:uint;
			tempRow=piece1.row;
			tempCol=piece1.col;
			piece1.row=piece2.row;
			piece1.col=piece2.col;
			piece2.row=tempRow;
			piece2.col=tempCol;
			grid[piece1.row][piece1.col]=piece1;
			grid[piece2.row][piece2.col]=piece2;
		}
		private function findAndRemoveMatches()
		{
			isTs=false;
			var matchList:Array=lookForMatches();
			for(var i:uint=0;i<matchList.length;i++)
			{
				for(var j:uint=0;j<matchList[i].length;j++)
				{
					if(gameSprite.contains(matchList[i][j]))
					{
						//matchList[i][j].row=null;
						//matchList[i][j].col=null;
						var point:int=(matchList[i].length-1)*50;
						
						gameSprite.removeChild(matchList[i][j]);
						grid[matchList[i][j].row][matchList[i][j].col]=null;
						affectAbove(matchList[i][j]);
						if(j==0)
						{
							var pb:PointBurst=new PointBurst(this,point,matchList[i][j].x,matchList[i][j].y);
							gameScore+=point;
							scoreDisplay.text=gameScore.toString();
							gameTime+=2;
							gameTime=(gameTime>30)?30:gameTime;
							displayTime.text=gameTime.toString();
						}
					}
				}
				
			}
			addNewPieces();
			for(i=0;i<8;i++)
			{
				for(j=0;j<8;j++)
				{
					grid[i][j].select.visible=false;
				}
			}
			if(matchList.length==0)
			{
				if(lookForPossibles()==false)
				{
					sisuo.x=94;
					sisuo.y=186;
					gameSprite.addChild(sisuo);
					sisuo.text="死锁状态！请点击重列";
					gameSprite.setChildIndex(sisuo,gameSprite.numChildren-1);
					time.stop();
				}
					
			}
		}
		private function lookForMatches():Array
		{
			var matches:Array=new Array();
			//horizontal
			for(var row:uint=0;row<8;row++)
			{
				for(var col:uint=0;col<6;col++)
				{
					var match:Array=getMatchHoriz(row,col);
					if(match.length>2)
					{
						matches.push(match);
						col+=match.length;
					}
				}
			}
			//vertical
			for(col=0;col<8;col++)
			{
				for(row=0;row<6;row++)
				{
					match=getMatchVert(row,col);
					if(match.length>2)
					{
						matches.push(match);
						row+=match.length;
					}
				}
			}
			return matches;
		}
		private function getMatchHoriz(row:uint,col:uint):Array
		{
			//trace(grid[row][col].row,grid[row][col].col);
			var match:Array=new Array(grid[row][col]);
			for(var i:uint=1;col+i<8;i++)
			{
				if(grid[row][col].type==grid[row][col+i].type)
					match.push(grid[row][col+i]);
				else
					return match;
			}
			return match;
		}
		private function getMatchVert(row:uint,col:uint):Array
		{
			var match:Array=new Array(grid[row][col]);
			for(var i:uint=1;row+i<8;i++)
			{
				if(grid[row][col].type==grid[row+i][col].type)
				{
					match.push(grid[row+i][col]);
				}
				else
				{
					return match;
				}
			}
			return match;
		}
		private function affectAbove(piece:Piece)
		{
			for(var row:int=piece.row-1;row>=0;row--)
			{
				if(grid[row][piece.col]!=null)
				{
					grid[row][piece.col].row++;
					grid[row+1][piece.col]=grid[row][piece.col];
					grid[row][piece.col]=null;
				}
			}
		}
		public function addNewPieces() 
		{
			for(var col:int=0;col<8;col++)
			{
				var missionPiece:int=0;
				for(var row:int=7;row>=0;row--)
				{
					//trace(row,col);
					if(grid[row][col]==null)
					{
						var newPiece:Piece=addPiece(row,col);
						newPiece.y=OFFSET_Y-SPACING-SPACING*missionPiece++;
						isDropping=true;
					}
				}
			}
		}
		public function lookForPossibles()
		{
			for(var i:int=0;i<8;i++)
			{
				for(var j:int=0;j<8;j++)
				{
					//水平方向 2+1
					if(matchPattern(i,j,[i,j+1],[[i-1,j-1],[i,j-2],[i+1,j-1],[i+1,j+2],[i,j+3],[i-1,j+2]]))
					{
						if(isTs)
						{
							var a:Piece=matchPattern(i,j,[i,j+1],[[i-1,j-1],[i,j-2],[i+1,j-1],[i+1,j+2],[i,j+3],[i-1,j+2]]);
							if(a.col>j)
								grid[i][j+2].select.visible=true;
							else
								grid[i][j-1].select.visible=true;
						}					
						return true;
					}
					//垂直方向 2+1
					else if(matchPattern(i,j,[i+1,j],[[i-1,j-1],[i-2,j],[i-1,j+1],[i+2,j-1],[i+3,j],[i+2,j+1]]))
					{
						if(isTs)
						{
							a=matchPattern(i,j,[i+1,j],[[i-1,j-1],[i-2,j],[i-1,j+1],[i+2,j-1],[i+3,j],[i+2,j+1]]);
							if(a.row>i)
								grid[i+2][j].select.visible=true;
							else
								grid[i-1][j].select.visible=true;
						}
						
						return true;
					}
						
					//水平方向  中空
					else if(matchPattern(i,j,[i,j+2],[[i-1,j+1],[i+1,j+1]]))
					{
						if(isTs)
						{
							a=matchPattern(i,j,[i,j+2],[[i-1,j+1],[i+1,j+1]]);
							grid[i][j+1].select.visible=true;
						}					
						return true;
					}
						
					//垂直方向  中空
					else if(matchPattern(i,j,[i+2,j],[[i+1,j-1],[i+1,j+1]]))
					{
						if(isTs)
						{
							a=matchPattern(i,j,[i+2,j],[[i+1,j-1],[i+1,j+1]]);
							grid[i+1][j].select.visible=true;
						}					
						return true;
					}
						
				}
			}
			return false;
		}
		public function matchPattern(row:int,col:int,mustHave:Array,possibles:Array)
		{
			var type:int=grid[row][col].type;
			if(!matchType(mustHave[0],mustHave[1],type))
				return false;
			//trace(possibles.length);
			for(var i:int=0;i<possibles.length;i++)
			{
				//trace(possibles);
				//trace(i);
				if(matchType(possibles[i][0],possibles[i][1],type))
				{
					if(isTs)
						grid[possibles[i][0]][possibles[i][1]].select.visible=true;
					return grid[possibles[i][0]][possibles[i][1]];
				}
			}
			return false;
		}
		public function matchType(row:int,col:int,type:int)
		{
			if(row<0 || row>7 || col<0 || col>7)
				return false;
			else if(grid[row][col].type==type)
			{
				return true;
			}
		}
		public function cleanUp()
		{
			gameScore=0;
			gameTime=30;
			tsNum=3;
			clNum=3;
			removeChild(finalScore);
		}
	}
}